home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ddj0897.zip / DYN401.ZIP / class / number.d < prev    next >
Text File  |  1996-07-10  |  5KB  |  270 lines

  1.  
  2. /*
  3.  *
  4.  *    Copyright (c) 1993-1996 Algorithms Corporation
  5.  *    3020 Liberty Hills Drive
  6.  *    Franklin, TN  37067
  7.  *
  8.  *    ALL RIGHTS RESERVED.
  9.  *
  10.  *
  11.  *
  12.  */
  13.  
  14.  
  15. #include <math.h>
  16.  
  17.  
  18. defclass  Number;
  19.  
  20.  
  21.  
  22. static    double    Round(double n, int p)    /*  round n to p places     */
  23. {
  24.     double    r;
  25.  
  26.     r = pow(10.0, (double) p);
  27.     r = floor(.5 + fabs(n * r)) / r;
  28.     if (n <    0.0)    return(-r);
  29.     return(r);
  30. }
  31.  
  32. static    int    Ndrgtb(double n, int b)    /* returns the number of digits    right of decimal point */
  33. {
  34.     double    base = b;
  35.     int    i;
  36.  
  37.     n = n < 0.0 ? -n : n;
  38.     i = 0;
  39.     while (i < 20)    {
  40.         n -= floor(n);
  41.         if (1E-12 >= n)     break;
  42.         i++;
  43.         n = Round(n*base, 13);
  44.     }
  45.     return(i);
  46. }
  47.  
  48.  
  49.  
  50. /*    Numeric    formatter:
  51. *    r = Nfmtb(n, b,    t, w, d, s);
  52. *    double    n    number to be formatted
  53. *    int    b    base
  54. *    char *t        type of    format    - any combination of the following:
  55. *            B = blank if zero
  56. *            C = add    commas
  57. *            L = left justify number
  58. *            P = put    perenthises around negative numbers
  59. *            Z = zero fill
  60. *            D = floating dollar sign
  61. *            U = uppercase letters in conversion
  62. *
  63. *    int  w        total field width
  64. *    ind  d        number of decimal places
  65. *    char  s[w+1]    result of format
  66. *    int  r        pointer    to result of format
  67. *
  68. *    example:
  69. *
  70. *        r = Nfmt(-12345.348, "CP", 12, 2, s);
  71. *
  72. *        result in s:    (12,345.35)
  73. */
  74.  
  75. static    char    *Nfmtb(double n, int b, char *t, int wth, int d, char *s)
  76. {
  77.     register int    si, i;
  78.     int    sign, blnk, comma, left, paren,    zfill, nd, dol,    tw, dl,    ez, ucase, cf=3, w=wth;
  79.     double    base;
  80.     static    char    alpha[]    = "0123456789abcdefghijklmnopqrstuvwxyz";
  81.  
  82.     if (b <    2  ||  b > (int)(sizeof(alpha)-1))
  83.         b = 10;
  84.     base = b;
  85.     if (sign = n < 0.0)
  86.         n = -n;
  87.  
  88.     /*  round number  */
  89.     if (d >= 0)  {
  90.         double    r = pow(base, (double) d);
  91.         n = floor(base/20.0 + n * r) / r;
  92.     }
  93.     
  94.     switch (b)  {
  95.         case 10:
  96.             cf = 3;
  97.             dl = n < 1.0 ? 0 : 1 + (int) log10(n);    /* # of    digits left of .  */
  98.             break;
  99.         case 2:
  100.             cf = 4;
  101.             dl = n < 1.0 ? 0 : 1 + (int) (log(n)/.6931471806);  /* # of digits left    of .  */
  102.             break;
  103.         case 8:
  104.             cf = 3;
  105.             dl = n < 1.0 ? 0 : 1 + (int) (log(n)/2.079441542);  /* # of digits left    of .  */
  106.             break;
  107.         case 16:
  108.             cf = 4;
  109.             dl = n < 1.0 ? 0 : 1 + (int) (log(n)/2.772588722);  /* # of digits left    of .  */
  110.             break;
  111.         default:
  112.             cf = 3;
  113.             dl = n < 1.0 ? 0 : 1 + (int) (log(n)/log(base));  /* # of digits left of .  */
  114.             break;
  115.     }
  116.     if (d <    0)
  117.         d = Ndrgtb(n, b);
  118.     blnk = comma = left = paren = zfill = dol = ucase = 0;
  119.     if (t)
  120.         while (*t)
  121.             switch    (*t++)    {
  122.             case  'B':    blnk  =    1;        break;
  123.             case  'C':    comma =    (dl - 1) / cf;    break;
  124.             case  'L':    left  =    1;        break;
  125.             case  'P':    paren =    1;        break;
  126.             case  'Z':    zfill =    1;        break;
  127.             case  'D':    dol   =    1;        break;
  128.             case  'U':    ucase =    1;        break;
  129.             }
  130.  
  131.     /*  calculate what the number should take up    */
  132.  
  133.     ez = n < 1.0;
  134.     tw = dol + paren + comma + sign    + dl + d + !!d + ez;
  135.  
  136.     if (w <    1)
  137.         w = tw;
  138.     else  if (tw > w)  {
  139.         if (ez)
  140.             tw -= ez--;
  141.         if ((i=dol)  &&  tw > w)
  142.             tw -= dol--;
  143.         if (tw > w  &&    comma)    {
  144.             tw -= comma;
  145.             comma =    0;
  146.         }
  147.         if (tw < w  &&    i)  {
  148.             tw++;
  149.             dol = 1;
  150.         }
  151.         if (tw > w  &&    paren)
  152.             tw -= paren--;
  153.         if (tw > w)  {
  154. nofit:
  155.             for (i=0 ; i < w ; )
  156.                 s[i++] = '*';
  157.             s[i] = '\0';
  158.             return(s);
  159.         }
  160.     }
  161.  
  162.     n = floor(.5 + n * floor(.5 + pow(base,    (double) d)));
  163.     if (blnk && n == 0.0)  {
  164.         for (i=0 ; i < wth ; )
  165.             s[i++] = ' ';
  166.         s[wth] = '\0';
  167.         return(s);
  168.     }
  169.     s[si = w] = '\0';
  170.     if (left  &&  w    > tw)  {
  171.         i = w -    tw;
  172.         while (i--)
  173.             s[--si]    = ' ';
  174.     }
  175.     if (paren)
  176.         s[--si]    = sign ? ')' : ' ';
  177.     for (nd=0 ; nd < d  &&    si ; nd++)  {
  178.         n /= base;
  179.         i = (int) floor(base * (n - floor(n)) + .5);
  180.         n = floor(n);
  181.         s[--si]    = ucase    && i > 9 ? alpha[i]+('A'-'a') :    alpha[i];
  182.     }
  183.     if (d)
  184.         if (si)
  185.             s[--si]    = '.';
  186.         else
  187.             n = 1.0;
  188.     if (ez    &&  si > sign +    dol)
  189.         s[--si]    = '0';
  190.     nd = 0;
  191.     while (n > 0.0    &&  si)
  192.         if (comma && nd    == cf)    {
  193.             s[--si]    = ',';
  194.             nd = 0;
  195.         }  else     {
  196.             n /= base;
  197.             i = (int) floor(base * (n - floor(n)) + .5);
  198.             n = floor(n);
  199.             s[--si]    = ucase    && i > 9 ? alpha[i]+('A'-'a') :    alpha[i];
  200.             nd++;
  201.         }
  202.     if (zfill)  {
  203.         i = sign + dol;
  204.         while (si > i)
  205.             s[--si]    = '0';
  206.     }
  207.     if (sign)
  208.         if (si)
  209.             s[--si]    = paren    ? '(' :    '-';
  210.         else
  211.             n = 1.0;    /*  signal error condition    */
  212.     if (dol     &&  si)
  213.         s[--si]    = '$';
  214.     while (si)
  215.         s[--si]    = ' ';
  216.     if (n != 0.0)
  217.         goto nofit;   /*  should never happen. but just    incase    */
  218.     return(s);
  219. }
  220.  
  221. imeth    gFormatNumber, <vFormat> (char *msk, int wth, int dp)
  222. {
  223.     char    buf[80];
  224.  
  225.     Nfmtb(gDoubleValue(self), 10, msk, wth, dp, buf);
  226.     return gNewWithStr(String, buf);
  227. }
  228.  
  229. #if 0
  230.  
  231. //imeth    int    gHash()
  232. {
  233.     double    t;
  234.  
  235.     t = .6125423371    * gDoubleValue(self);
  236.     t = t < 0.0 ? -t : t;
  237.     return (int) (BIG_INT * (t - floor(t)));
  238. }
  239.  
  240. #endif
  241.  
  242. imeth    int    gCompare(obj)
  243. {
  244.     double    sv, ov;
  245.  
  246.     ChkArg(obj, 2);
  247.     if (!gIsKindOf(obj, Number))
  248.         return gCompare(super, obj);
  249.     if ((sv=gDoubleValue(self)) < (ov=gDoubleValue(obj)))
  250.         return -1;
  251.     else if (sv == ov)
  252.         return 0;
  253.     else
  254.         return 1;
  255. }
  256.  
  257.  
  258. /*
  259.  *
  260.  *    Copyright (c) 1993-1996 Algorithms Corporation
  261.  *    3020 Liberty Hills Drive
  262.  *    Franklin, TN  37067
  263.  *
  264.  *    ALL RIGHTS RESERVED.
  265.  *
  266.  *
  267.  *
  268.  */
  269.  
  270.